package com.shengyu.framework.tenant.core.db;

import cn.hutool.core.collection.CollUtil;
import com.shengyu.framework.common.enums.UserTypeEnum;
import com.shengyu.framework.tenant.config.TenantProperties;
import com.shengyu.framework.tenant.core.context.TenantContextHolder;
import com.shengyu.framework.web.core.util.WebFrameworkUtils;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;

import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

/**
 * 基于 MyBatis Plus 多租户的功能，实现 DB 层面的多租户的功能
 *
 * @author 圣钰科技
 */
public class TenantDatabaseInterceptor implements TenantLineHandler {

    private final Set<String> ignoreTables = new HashSet<>();

    private final Set<String> ignoreTablesPrefix = new HashSet<>();

    public TenantDatabaseInterceptor(TenantProperties properties) {
        // 不同 DB 下，大小写的习惯不同，所以需要都添加进去
        properties.getIgnoreTables().forEach(table -> {
            ignoreTables.add(table.toLowerCase());
            ignoreTables.add(table.toUpperCase());
        });
        // 在 OracleKeyGenerator 中，生成主键时，会查询这个表，查询这个表后，会自动拼接 TENANT_ID 导致报错
        ignoreTables.add("DUAL");
        //需要忽略的表前缀
        properties.getIgnoreTablesPrefix().forEach(tablesPrefix -> {
            ignoreTablesPrefix.add(tablesPrefix);
        });
    }

    @Override
    public Expression getTenantId() {
        return new LongValue(TenantContextHolder.getRequiredTenantId());
    }

    @Override
    public boolean ignoreTable(String tableName) {
        //平台用户默认不拼接租户id(并且是获取的租户id为空的情况)
        boolean userType = Objects.isNull(TenantContextHolder.getTenantId()) && UserTypeEnum.PLATFORM.getValue().equals(WebFrameworkUtils.getLoginUserType());
        boolean isIgnore = Boolean.FALSE;
        //需要忽略的表前缀处理
        for (String tablesPrefix : ignoreTablesPrefix) {
            //匹配到一个前缀就可以跳出循环体了
            if (tableName.startsWith(tablesPrefix)) {
                isIgnore = Boolean.TRUE;
                break;
            }
        }
        return TenantContextHolder.isIgnore() // 情况一，全局忽略多租户
            || CollUtil.contains(ignoreTables, tableName) // 情况二，忽略多租户的表
            || isIgnore  // 情况三，自定义忽略多租户的表前缀
            || userType  //情况三，平台用户默认不拼接租户id
        ;
    }

}
